﻿
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using sharpxbot.Plugins.BibleSearch.Data;
using sharpxbot.Utils.Database;
namespace sharpxbot.Plugins.BibleSearch
{
    public class BibleCache
    {
        public BibleCache(IDatabase db)
        {
            if (db == null)
                throw new NullReferenceException("Illegal null-reference database BibleCache constructor");

            chapters = new Dictionary<int, Chapter>();
            bookAbbreviations = new Dictionary<int, string>();
            abbreviationsToBooks = new Dictionary<string, int>();

            BuildChaptersIndex(db);
            BuildBookAbbreviationsIndex(db);
        }

        public Chapter GetChapterByID(int chapterID)
        {
            Chapter result = null;
            chapters.TryGetValue(chapterID, out result);

            return result;
        }

        public string GetBookNameAbbreviationByID(int bookID)
        {
            string result = null;
            bookAbbreviations.TryGetValue(bookID, out result);

            return result;
        }

        public int GetBookIDByAbbreviation(string bookNameAbbreviation)
        {
            int result = -1;

            string matchingAbbreviation = abbreviationsToBooks.Keys.
                Where(k => k.ToUpper() == bookNameAbbreviation.ToUpper()).FirstOrDefault();

            if (!String.IsNullOrWhiteSpace(matchingAbbreviation))
            {
                abbreviationsToBooks.TryGetValue(matchingAbbreviation, out result);
            }

            return result;
        }

        private void BuildChaptersIndex(IDatabase db)
        {
            try
            {
                DbCommand cmd = db.CreateCommand("select id, chapter_index, book_id from chapters");
                DbDataReader reader = null;
                try
                {
                    reader = cmd.ExecuteReader();

                    while (reader.Read())
                    {
                        int ID = (int)reader.GetInt64(0);
                        string ChapterIndex = reader.GetString(1);
                        int BookID = reader.GetInt32(2);

                        Chapter c = new Chapter()
                        {
                            ID = ID,
                            ChapterIndex = ChapterIndex,
                            BookID = BookID
                        };

                        chapters[ID] = c;
                    }
                }
                catch { }
                finally
                {
                    if (reader != null)
                        reader.Close();
                }
            }
            catch { }
        }

        private void BuildBookAbbreviationsIndex(IDatabase db)
        {
            try
            {
                char[] abbrTrim = new char[] { '.' };

                DbCommand cmd = db.CreateCommand("select abbreviation, book_id from book_names_abbr");
                DbDataReader reader = null;
                try
                {
                    reader = cmd.ExecuteReader();

                    while (reader.Read())
                    {
                        string abbr = reader.GetString(0);
                        int bookID = reader.GetInt32(1);

                        if (!bookAbbreviations.ContainsKey(bookID)) // only first abbreviation is canonical
                            bookAbbreviations[bookID] = abbr;

                        abbreviationsToBooks[abbr.TrimEnd(abbrTrim)] = bookID;
                    }
                }
                catch { }
                finally
                {
                    if (reader != null)
                        reader.Close();
                }
            }
            catch { }
        }

        Dictionary<int, string> bookAbbreviations; // book_id => book_abbreviation
        Dictionary<string, int> abbreviationsToBooks; // book_abbreviation => book_id
        Dictionary<int, Chapter> chapters; // chapter_id => chapter
    }
}
